﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Precision;

namespace NetTopologySuite.Operation.Overlay.Snap
{
	public class SnapOverlayOp
	{
		public static IGeometry Overlay(IGeometry g0, IGeometry g1, SpatialFunction opCode)
		{
			return new SnapOverlayOp(g0, g1).GetResultGeometry(opCode);
		}

		public static IGeometry Intersection(IGeometry g0, IGeometry g1)
		{
			return SnapOverlayOp.Overlay(g0, g1, SpatialFunction.Intersection);
		}

		public static IGeometry Union(IGeometry g0, IGeometry g1)
		{
			return SnapOverlayOp.Overlay(g0, g1, SpatialFunction.Union);
		}

		public static IGeometry Difference(IGeometry g0, IGeometry g1)
		{
			return SnapOverlayOp.Overlay(g0, g1, SpatialFunction.Difference);
		}

		public static IGeometry SymDifference(IGeometry g0, IGeometry g1)
		{
			return SnapOverlayOp.Overlay(g0, g1, SpatialFunction.SymDifference);
		}

		public SnapOverlayOp(IGeometry g1, IGeometry g2)
		{
			this._geom[0] = g1;
			this._geom[1] = g2;
			this.ComputeSnapTolerance();
		}

		private void ComputeSnapTolerance()
		{
			this._snapTolerance = GeometrySnapper.ComputeOverlaySnapTolerance(this._geom[0], this._geom[1]);
		}

		public IGeometry GetResultGeometry(SpatialFunction opCode)
		{
			IGeometry[] array = this.Snap(this._geom);
			IGeometry geom = OverlayOp.Overlay(array[0], array[1], opCode);
			return this.PrepareResult(geom);
		}

		private IGeometry SelfSnap(IGeometry geom)
		{
			return new GeometrySnapper(geom).SnapTo(geom, this._snapTolerance);
		}

		private IGeometry[] Snap(IGeometry[] geom)
		{
			IGeometry[] array = this.RemoveCommonBits(geom);
			return GeometrySnapper.Snap(array[0], array[1], this._snapTolerance);
		}

		private IGeometry PrepareResult(IGeometry geom)
		{
			this.cbr.AddCommonBits(geom);
			return geom;
		}

		private IGeometry[] RemoveCommonBits(IGeometry[] geom)
		{
			this.cbr = new CommonBitsRemover();
			this.cbr.Add(geom[0]);
			this.cbr.Add(geom[1]);
			return new IGeometry[]
			{
				this.cbr.RemoveCommonBits((IGeometry)geom[0].Clone()),
				this.cbr.RemoveCommonBits((IGeometry)geom[1].Clone())
			};
		}

		private void CheckValid(IGeometry g)
		{
			bool isValid = g.IsValid;
		}

		private readonly IGeometry[] _geom = new IGeometry[2];

		private double _snapTolerance;

		private CommonBitsRemover cbr;
	}
}
